#include<stdio.h>
#include<unistd.h>
#include<sys/stat.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<dirent.h>
#include<stdlib.h>
#include<string.h>
#include<pthread.h>
#include<fcntl.h>

#define DESTDIR "/home/sh/workshop/os-exp/destdir"

int err=0;//记录创建线程错误
pthread_t tid=0;//记录线程id
typedef struct thread_count{
    int count;
    pthread_mutex_t lock;
}t_count, *count_ptr;
count_ptr cp;


#define BUFFER_SIZE 1
extern int errno;
void* mycp(void* argv){
    //增加线程数
    pthread_mutex_lock(&cp->lock);
    cp->count+=1;
    pthread_mutex_unlock(&cp->lock);

    char** files = (char**)argv;
    char originFile[255];
    char targetFile[255];
    strcpy(originFile,(char*)files[0]);
    strcpy(targetFile,(char*)files[1]);
    printf("In mycp: %s,%s\n",originFile,targetFile);
    int fr = open(originFile,O_RDONLY);
    int fw = open(targetFile,O_WRONLY);
    //如果源文件不存在或是文件夹，报错
    if(fr == -1){
        perror(originFile);
        return 0;
    }
    //如果目标文件存在，给出提示
    if(fw != -1){
        printf("%s already exists. Enter 1 to overwrite or enter 2 to append.\n",targetFile);
        close(fw);
        int flag = getchar();
        if(flag == '1'){
            fw = open(targetFile,O_WRONLY|O_TRUNC);
        }else if(flag == '2'){
            fw = open(targetFile,O_WRONLY|O_APPEND);
        }else{
            printf("Got wrong input.\n");
        }
    }else{
        struct stat st;
        err=stat(targetFile,&st);
        if(S_ISDIR(st.st_mode)&&err!=-1){//存在但是dir
            char* ofname=strrchr(originFile,'/');
            if(ofname!=NULL){
                strcat(targetFile,"/");
                strcat(targetFile,ofname);
            }else{
                strcat(targetFile,"/");
                strcat(targetFile,originFile);
            }
        }
        //不是dir且不存在
        // fw = open(targetFile,O_CREAT|O_EXCL|O_WRONLY,S_IRUSR|S_IWUSR);
        fw = creat(targetFile,S_IRUSR|S_IWUSR);
        if(fw==-1){
            printf("%s:target directory doesn't exits.\n",targetFile);
        }
    }
    char buf[BUFFER_SIZE]={'\0'};
    int readLen=read(fr,buf,BUFFER_SIZE);
    int writeLen=write(fw,buf,sizeof(buf));
    while(readLen != 0){
        readLen=read(fr,buf,BUFFER_SIZE);
        writeLen=write(fw,buf,sizeof(buf));
    }
    printf("%s====>%s\n",originFile,targetFile);
    close(fr);
    close(fw);
    free(files[0]);
    free(argv);

    //减少线程数
    pthread_mutex_lock(&cp->lock);
    cp->count-=1;
    pthread_mutex_unlock(&cp->lock);

    pthread_exit((void*)0);
}

void* myls(void* dirpath){
    //增加线程数
    pthread_mutex_lock(&cp->lock);
    cp->count+=1;
    pthread_mutex_unlock(&cp->lock);

    struct dirent *ep;
    char* filepath = (char*)malloc(120);
    DIR* dp = opendir((char*)dirpath);
    if(dp==NULL){
        printf("directory doesnot exists.\n");
        return 0;
    }else{
        while(ep = readdir(dp)){
            struct stat st;
            sprintf(filepath,"%s/%s",(char*)dirpath,ep->d_name);

            if(stat(filepath,&st)==-1){
                printf("read failed.\n");
                return 0;
            }
            if(strcmp(ep->d_name,".")==0||strcmp(ep->d_name,"..")==0){
                //如果是本目录或父目录，那就什么都不干
            }else if(S_ISDIR(st.st_mode)){
                char* mylsFilePath=(char*)malloc(255);//传入filepath的话会导致多线程同时访问的时候出错，所以要新分配空间
                strcpy(mylsFilePath,filepath);
                pthread_attr_t attr;
                pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);//进程设为分离状态
                err=pthread_create(&tid,&attr,myls,(void*)mylsFilePath);
                if(err!=0){
                    printf("pthread create failFed.\n");
                    exit(0);
                }
            }else{
                char* mycpFilePath=(char*)malloc(255);
                strcpy(mycpFilePath,filepath);
                char** files = (char**)malloc(sizeof(char*)*2);
                files[0] = mycpFilePath;
                files[1] = DESTDIR;
                printf("In myls: %s,%s\n",files[0],files[1]);
                pthread_attr_t attr;
                pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
                err=pthread_create(&tid,&attr,mycp,(void*)files);
                if(err!=0){
                    printf("pthread create failed.\n");
                    exit(0);
                }
            }
        }
    }
    closedir(dp);
    free(dirpath);
    free(filepath);

    //减少线程数
    pthread_mutex_lock(&cp->lock);
    cp->count-=1;
    pthread_mutex_unlock(&cp->lock);

    pthread_exit((void*)0);
}

int main(int argc, char* argv[]){
    //TODO
    struct dirent *ep;
    char* dirpath = (char*)malloc(255);
    cp = (count_ptr)malloc(sizeof(t_count));
    cp->count=0;
    pthread_mutex_init(&(cp->lock),NULL);
    if(argc>2){
        printf("%s requires 1 arguments, but got %d.\n",argv[0],argc-1);
        exit(0);
    }else if(argc == 1){
        getcwd(dirpath,255);
    }else if(argc == 2){
        strcpy(dirpath,argv[1]);
    }
    err=pthread_create(&tid,NULL,myls,(void*)dirpath);
    if(err!=0){
        printf("pthread create failed.\n");
        exit(0);
    }
    sleep(1);//还是要等一下，要不然获取cp->count的时候线程还没跑起来
    while(cp->count!=0){
        //继续等
    }
    return 0;
}